<!DOCTYPE html>
<html  lang="zh-CN" >
    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, minimum-scale=1, initial-scale=1, maximum-scale=5, viewport-fit=cover">
    <title>Flink-几道面试题 | 学为我用</title>
    <meta name="description" content="前言前两天面试腾讯大数据岗，被面试官虐的惨不忍睹啊。也许是面试官虐开心了，既然放我过了。主要问题集中在Flink这一块，赶紧记录下来。 Flink 事件时间语义flink有三种时间语义，分别是 Processing Time &#x2F; Event Time &#x2F; Ingestion Time Ingestion Time当事件进入Flink时，会自动打一个时间标签，这个时间标签就是Ingestion，翻译">
<meta property="og:type" content="article">
<meta property="og:title" content="Flink-几道面试题">
<meta property="og:url" content="https://123zhangzhenbin.gitee.io/zzbomb/2020/10/27/202010270852-flink-windows/index.html">
<meta property="og:site_name" content="学为我用">
<meta property="og:description" content="前言前两天面试腾讯大数据岗，被面试官虐的惨不忍睹啊。也许是面试官虐开心了，既然放我过了。主要问题集中在Flink这一块，赶紧记录下来。 Flink 事件时间语义flink有三种时间语义，分别是 Processing Time &#x2F; Event Time &#x2F; Ingestion Time Ingestion Time当事件进入Flink时，会自动打一个时间标签，这个时间标签就是Ingestion，翻译">
<meta property="og:locale" content="zh_CN">
<meta property="article:published_time" content="2020-10-27T00:53:44.000Z">
<meta property="article:modified_time" content="2020-10-29T10:24:50.817Z">
<meta property="article:author" content="章瑱彬">
<meta property="article:tag" content="大数据">
<meta name="twitter:card" content="summary">

    
    <link rel="icon" href="/zzbomb/images/favicon_128.ico" type="image/x-icon">

    
<link rel="stylesheet" href="/zzbomb/css/common.min.css">



    
    
    
    
        <link href="//cdn.jsdelivr.net/npm/lightgallery.js@1.1.3/dist/css/lightgallery.min.css" rel="stylesheet">
    
    
    
<link rel="stylesheet" href="/zzbomb/css/iconfont.min.css">

    
<meta name="generator" content="Hexo 4.2.1"></head>

    <body>
        <header class="header header-fixture">
    <div class="profile-search-wrap flex sm:block">
        
        
        <div class="profile sm:text-center md:px-1 lg:px-3 sm:pb-4 sm:pt-6">
            <a id="avatar" role="link" href="https://gitee.com/123zhangzhenbin" class="inline-block lg:w-16 lg:h-16 w-8 h-8 m-2" target="_blank" rel="noopener" rel="noreferrer" >
                <img src="/zzbomb/images/g.jpg" class="rounded-full" alt="avatar">
            </a>
            <h2 id="name" class="hidden lg:block">ZZB</h2>
            <h3 id="title" class="hidden xl:block">Java，大数据，人工智能，区块链</h3>
            
            <small id="location" class="hidden lg:block">
                <i class="iconfont icon-map-icon"></i>
                DongGuan, China
            </small>
            
        </div>
        
        
<div class="search flex-1 flex lg:inline-block sm:hidden lg:px-4 lg:mt-2 lg:mb-4 lg:w-full">
    <form id="search-form" class="my-auto flex-1 lg:border lg:border-solid lg:border-gray-200">
        <div class="input-group table bg-gray-100 lg:bg-white w-full">
            <input id="search-input" type="text" placeholder="搜索" class="inline-block w-full bg-gray-100 lg:bg-white">
            <span class="table-cell">
                <button name="search tigger button" disabled>
                    <i class="iconfont icon-search m-2"></i>
                </button>
            </span>
        </div>
    </form>
        
<script id="search-teamplate" type="text/html" data-path="/zzbomb/content.json">
    <div>
        <div class="search-header bg-gray-400">
            <input id="actual-search-input" model="keyword" ref="input" class="inline-block w-full h-10 px-2 py-1" placeholder="搜索" type="text">
        </div>
        <div class="search-result bg-gray-200">
            {{#each searchPosts}}
            <a href="/{{ path }}" class="result-item block px-2 pb-3 mb-1 pt-1 hover:bg-indigo-100">
                <i class="iconfont icon-file"></i>
                <h1 class="result-title inline font-medium text-lg">{{ title }}</h1>
                <p class="result-content text-gray-600 text-sm">{{{ text }}}</p>
            </a>
            {{/each}}
        </div>
    </div>
</script>

</div>


        <button name="menu toogle button" id="menu-toggle-btn" class="block sm:hidden p-3" role="button" aria-expanded="false">
            <i class="iconfont icon-hamburger"></i>
        </button>
    </div>
    <nav id="menu-nav" class="hidden sm:flex flex-col">
        
        
            <div class="menu-item menu-home" role="menuitem">
                <a href="/zzbomb/.">
                    <i class="iconfont icon-home" aria-hidden="true"></i>
                    <span class="menu-title">首页</span>
                </a>
            </div>
        
        
            <div class="menu-item menu-archives" role="menuitem">
                <a href="/zzbomb/archives">
                    <i class="iconfont icon-archive" aria-hidden="true"></i>
                    <span class="menu-title">归档</span>
                </a>
            </div>
        
        
            <div class="menu-item menu-categories" role="menuitem">
                <a href="/zzbomb/categories">
                    <i class="iconfont icon-folder" aria-hidden="true"></i>
                    <span class="menu-title">分类</span>
                </a>
            </div>
        
        
            <div class="menu-item menu-tags" role="menuitem">
                <a href="/zzbomb/tags">
                    <i class="iconfont icon-tag" aria-hidden="true"></i>
                    <span class="menu-title">标签</span>
                </a>
            </div>
        
        
            <div class="menu-item menu-repository" role="menuitem">
                <a href="/zzbomb/repository">
                    <i class="iconfont icon-project" aria-hidden="true"></i>
                    <span class="menu-title">项目</span>
                </a>
            </div>
        
        
            <div class="menu-item menu-links" role="menuitem">
                <a href="/zzbomb/links">
                    <i class="iconfont icon-friend" aria-hidden="true"></i>
                    <span class="menu-title">友链</span>
                </a>
            </div>
        
        
            <div class="menu-item menu-about" role="menuitem">
                <a href="/zzbomb/about">
                    <i class="iconfont icon-cup" aria-hidden="true"></i>
                    <span class="menu-title">关于</span>
                </a>
            </div>
        
        
<div class="social-links flex sm:flex-col lg:hidden mt-5">
    
        <span class="social-item text-center">
            <a href="https://gitee.com/123zhangzhenbin" target="_blank" rel="noopener">
                <i class="iconfont social-icon icon-github"></i>
                <span class="menu-title hidden lg:inline">menu.github</span>
            </a>
        </span>
    
</div>


    </nav>
</header>

        <section class="main-section">
            
    <main class="flex-1 px-4 py-12 md:px-5 lg:px-8 lg:py-4 relative min-h-screen">
    

    <article class="content article article-archives article-type-list" itemscope="">
        <header class="article-header">
            
    
        <h1 class="article-title text-lg" itemprop="name">
            Flink-几道面试题
        </h1>
    



            <p class="article-meta mb-3 text-xs">
                <span class="article-date">
    <i class="iconfont icon-calendar-check"></i>
	<a href="/zzbomb/2020/10/27/202010270852-flink-windows/" class="article-date">
	  <time datetime="2020-10-27T00:53:44.000Z" itemprop="datePublished">10月 27</time>
	</a>
</span>

                

                
    <span class="article-tags">
    <i class="iconfont icon-tag"></i>
    <a class="article-tag-link" href="/zzbomb/tags/%E5%A4%A7%E6%95%B0%E6%8D%AE/" rel="tag">大数据</a>
  </span>


                <span class="_partial/post-comment"><i class="icon icon-comment"></i>
                    <a href="/zzbomb/2020/10/27/202010270852-flink-windows/#comments" class="article-comment-link">
                        评论
                    </a>
                </span>
                

            </p>
        </header>
        <div class="marked-body article-body">
            <h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>前两天面试腾讯大数据岗，被面试官虐的惨不忍睹啊。也许是面试官虐开心了，既然放我过了。主要问题集中在Flink这一块，赶紧记录下来。</p>
<h2 id="Flink-事件时间语义"><a href="#Flink-事件时间语义" class="headerlink" title="Flink 事件时间语义"></a>Flink 事件时间语义</h2><p>flink有三种时间语义，分别是 Processing Time / Event Time / Ingestion Time</p>
<h3 id="Ingestion-Time"><a href="#Ingestion-Time" class="headerlink" title="Ingestion Time"></a>Ingestion Time</h3><p>当事件进入Flink时，会自动打一个时间标签，这个时间标签就是Ingestion，翻译过来是摄入时间。<br>一般来说，摄入时间在EventTime 和 Processing之间，且因为摄入时间是Flink自己打的时间戳标签，所以可以保证他的顺序性。</p>
<h3 id="Event-Time"><a href="#Event-Time" class="headerlink" title="Event Time"></a>Event Time</h3><p>事件本事的时间，在事件字段中<br>他的特点是，时间由事件本身携带，可能存在迟到数据的情况。如果使用事件时间，一般会设置水印时间。</p>
<h3 id="Processing-Time"><a href="#Processing-Time" class="headerlink" title="Processing Time"></a>Processing Time</h3><p>事件被处理时的当前系统时间</p>
<h3 id="使用场景"><a href="#使用场景" class="headerlink" title="使用场景"></a>使用场景</h3><p>在Flink中的Processing Time 和 Event Time 的使用场景较多，IngestionTime交少。<br>在我们不关心时间，不关心顺序，只需要时间段内有数据过来就好了，就用ProcessingTime</p>
<p>如果我们关心时间，关心顺序，就使用EventTime，选择EventTime同时需要考虑一下几个问题:</p>
<ol>
<li>迟到数据</li>
<li>网络抖动</li>
<li>服务可用性</li>
<li>一致性语义</li>
</ol>
<h2 id="Flink-窗口类型和水印"><a href="#Flink-窗口类型和水印" class="headerlink" title="Flink 窗口类型和水印"></a>Flink 窗口类型和水印</h2><p>按窗口的驱动方式来区分，窗口分为时间窗口和数量窗口。<br>按照窗口的划分方式来区分，分为滚动窗口，滑动窗口，和回话窗口。</p>
<p>时间窗口就是通过时间段来划分窗口，数量窗口就是通过数据量到达一点程度后自动拆分的窗口。<br>一般来说，时间窗口用的比较多，也更复杂一些。下面就时间窗口进行详解。</p>
<h3 id="滚动窗口（Tumbling-Windows）"><a href="#滚动窗口（Tumbling-Windows）" class="headerlink" title="滚动窗口（Tumbling Windows）"></a>滚动窗口（Tumbling Windows）</h3><p>每一个窗口的时间段是相对独立的，不会相互重叠</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><code class="hljs java">val input: DataStream[T] = ...<br><br><span class="hljs-comment">// tumbling event-time windows</span><br>input<br>    .keyBy(...)<br>    .window(TumblingEventTimeWindows.of(Time.seconds(<span class="hljs-number">5</span>)))<br>    .&lt;window function&gt;(...)<br><br><span class="hljs-comment">// tumbling processing-time windows</span><br>input<br>    .keyBy(...)<br>    .window(TumblingProcessingTimeWindows.of(Time.seconds(<span class="hljs-number">5</span>)))<br>    .&lt;window function&gt;(...)<br><br><span class="hljs-comment">// 1 hour tumbling event-time windows offset by 15 minutes.</span><br>input<br>    .keyBy(...)<br>    .window(TumblingEventTimeWindows.of(Time.hours(<span class="hljs-number">1</span>), Time.minutes(<span class="hljs-number">15</span>)))<br>    .&lt;window function&gt;(...)<br></code></pre></td></tr></table></figure>
<p>有些代码中，设置时间使用的是timeWindow而非window，比如，input.keyBy(…).timeWindow(Time.seconds(1))。timeWindow是一种简写。当我们在执行环境设置了TimeCharacteristic.EventTime时，Flink对应调用TumblingEventTimeWindows；如果我们基于TimeCharacteristic.ProcessingTime，Flink使用TumblingProcessingTimeWindows。</p>
<h3 id="滑动窗口（Sliding-Windows）"><a href="#滑动窗口（Sliding-Windows）" class="headerlink" title="滑动窗口（Sliding Windows）"></a>滑动窗口（Sliding Windows）</h3><p>每次向前扩张一些时间，窗口与窗口之间会有重复。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><code class="hljs java">val input: DataStream[T] = ...<br><br><span class="hljs-comment">// sliding event-time windows</span><br>input<br>    .keyBy(...)<br>    .window(SlidingEventTimeWindows.of(Time.seconds(<span class="hljs-number">10</span>), Time.seconds(<span class="hljs-number">5</span>)))<br>    .&lt;window function&gt;(...)<br><br><span class="hljs-comment">// sliding processing-time windows</span><br>input<br>    .keyBy(&lt;...&gt;)<br>    .window(SlidingProcessingTimeWindows.of(Time.seconds(<span class="hljs-number">10</span>), Time.seconds(<span class="hljs-number">5</span>)))<br>    .&lt;window function&gt;(...)<br><br><span class="hljs-comment">// sliding processing-time windows offset by -8 hours</span><br>input<br>    .keyBy(&lt;...&gt;)<br>    .window(SlidingProcessingTimeWindows.of(Time.hours(<span class="hljs-number">12</span>), Time.hours(<span class="hljs-number">1</span>), Time.hours(-<span class="hljs-number">8</span>)))<br>    .&lt;window function&gt;(...)<br></code></pre></td></tr></table></figure>

<h3 id="会话窗口（Session-Windows）"><a href="#会话窗口（Session-Windows）" class="headerlink" title="会话窗口（Session Windows）"></a>会话窗口（Session Windows）</h3><p>将连续出现的数据放到同一个窗口，根据sessionGap设置空窗期时间，当一段时间没有数据且这段时间大于等于预设sessionGap就会自动切换窗口。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><code class="hljs java">val input: DataStream[T] = ...<br><br><span class="hljs-comment">// event-time session windows with static gap</span><br>input<br>    .keyBy(...)<br>    .window(EventTimeSessionWindows.withGap(Time.minutes(<span class="hljs-number">10</span>)))<br>    .&lt;window function&gt;(...)<br><br><span class="hljs-comment">// event-time session windows with dynamic gap</span><br>input<br>    .keyBy(...)<br>    .window(EventTimeSessionWindows.withDynamicGap(<span class="hljs-keyword">new</span> SessionWindowTimeGapExtractor[T] &#123;<br>      <span class="hljs-function">override def <span class="hljs-title">extract</span><span class="hljs-params">(element: T)</span>: Long </span>= &#123;<br>        <span class="hljs-comment">// determine and return session gap</span><br>      &#125;<br>    &#125;))<br>    .&lt;window function&gt;(...)<br><br><span class="hljs-comment">// processing-time session windows with static gap</span><br>input<br>    .keyBy(...)<br>    .window(ProcessingTimeSessionWindows.withGap(Time.minutes(<span class="hljs-number">10</span>)))<br>    .&lt;window function&gt;(...)<br><br><br><span class="hljs-comment">// processing-time session windows with dynamic gap</span><br>input<br>    .keyBy(...)<br>    .window(DynamicProcessingTimeSessionWindows.withDynamicGap(<span class="hljs-keyword">new</span> SessionWindowTimeGapExtractor[T] &#123;<br>      <span class="hljs-function">override def <span class="hljs-title">extract</span><span class="hljs-params">(element: T)</span>: Long </span>= &#123;<br>        <span class="hljs-comment">// determine and return session gap</span><br>      &#125;<br>    &#125;))<br>    .&lt;window function&gt;(...)<br></code></pre></td></tr></table></figure>

<h3 id="水印"><a href="#水印" class="headerlink" title="水印"></a>水印</h3><p>前面说了各种窗口，这些窗口通过水印时间来划分，水印本质上也是时间戳。通过设置水印，可以解决一段时间内的数据乱序问题。<br>通过水印触发窗口有2个条件：</p>
<ol>
<li>watermark时间 &gt;= window_end_time</li>
<li>在[window_start_time,window_end_time)中有数据存在</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">final</span> StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();<br>        <br><span class="hljs-comment">//指定使用eventTime作为时间标准</span><br>env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);<br> <br>SingleOutputStreamOperator&lt;String&gt; lines = env.socketTextStream(<span class="hljs-string">"192.168.1.33"</span>, <span class="hljs-number">9999</span>)<br>        .assignTimestampsAndWatermarks(<span class="hljs-keyword">new</span> BoundedOutOfOrdernessTimestampExtractor&lt;String&gt;(Time.seconds(<span class="hljs-number">0</span>)) &#123;<br>            <span class="hljs-comment">//将数据中的时间字段提取出来，转成Long类型,不改变输入的数据样式</span><br>            <span class="hljs-meta">@Override</span><br>            <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">long</span> <span class="hljs-title">extractTimestamp</span><span class="hljs-params">(String line)</span> </span>&#123;<br>                String[] fileds = line.split(<span class="hljs-string">","</span>);<br>                <span class="hljs-keyword">return</span> Long.parseLong(fileds[<span class="hljs-number">0</span>]);<br>            &#125;<br>        &#125;);<br></code></pre></td></tr></table></figure>

<h2 id="Flink-如何保证exactly-once语义"><a href="#Flink-如何保证exactly-once语义" class="headerlink" title="Flink 如何保证exactly-once语义"></a>Flink 如何保证exactly-once语义</h2><p>flink通过checkpoint保证exactly-once语义。<br>Flink有checkpoint和savepoint，<br>其中checkpoint是jobManager定时发起的，而savepoint则是手动或者在代码中控制的。<br>checkpoint结合rockDB可以快速增量存储状态，savepoint则是原生的存储（如HDFS）。<br>下面是如何手动的触发savepoint</p>
<figure class="highlight angelscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs angelscript"><span class="hljs-comment">//先启动Job</span><br>[<span class="hljs-symbol">root@</span>hadoop101 bin]# ./flink run -c com.bjsxt.flink.state.TestSavepoints -d /home/Flink-Demo<span class="hljs-number">-1.0</span>-SNAPSHOT.jar<br><br><span class="hljs-comment">//手动触发SavePoint，然后取消作业</span><br>[<span class="hljs-symbol">root@</span>hadoop101 bin]# ./flink savepoint <span class="hljs-number">6</span>ecb8cfda5a5200016ca6b01260b94ce<br><br>[<span class="hljs-symbol">root@</span>hadoop101 bin]# ./flink cancel <span class="hljs-number">6</span>ecb8cfda5a5200016ca6b01260b94ce<br><br><span class="hljs-comment">// 重故障点恢复</span><br>flink run \<br>-s hdfs:<span class="hljs-comment">//hadoop101:9000/savepoints/savepoint-6ecb8c-e56ccb88576a \</span><br>-c com.bjsxt.flink.state.TestSavepoints \<br>-d /home/Flink-Demo<span class="hljs-number">-1.0</span>-SNAPSHOT.jar<br></code></pre></td></tr></table></figure>

<p>spark中也有checkpoint，是针对driver程序出现故障的时候数据和状态的恢复，Flink的checkpoint就复杂得多。<br>flink的在传统的checkpoint特性上，增加了两阶段提交。这两方面的组合，让flink有了精确一次的能力。</p>
<p>flink的checkpoint机制是把程序处理的中间状态保存下来，当程序失败可以从最新的checkpoint中恢复，通过checkpoint的机制，flink可以实现精确一次和至少一次的语义。<br>barrier对齐发生在一个处理节点需要接收上游不同处理节点的数据，由于不同的上游节点数据处理速度不一致，那么就会导致下游节点接收到 barrier的时间点也会不一致，这时候就需要使用barrier对齐机制：在同一checkpoint中，先到达的barrier是否需要等待其他处理节点barrier达到后在发送后续数据，barrier将数据流分为前后两个checkpoint(chk n,chk n+1)的概念，如果不等待那么就会导致chk n的阶段处理了chk n+1阶段的数据，但是在source端所记录的消费偏移量又一致，如果chk n成功之后，后续的任务处理失败，任务重启会消费chk n+1阶段数据，就会到致数据重复消息，如果barrier等待就不会出现这样情况，因此barrier需要对齐那么就是实现exectly once语义，否则实现的是at least once语义。由于状态是属于flink内部存储，所以flink 仅仅满足内部exactly once语义。</p>
<h2 id="Flink-迟到数据如何处理"><a href="#Flink-迟到数据如何处理" class="headerlink" title="Flink 迟到数据如何处理"></a>Flink 迟到数据如何处理</h2><p>迟到数据是指即使设置了水印和窗口，仍然有错序的情况，可以通过旁路输出来解决。<br>sideOutputLateData(outputTag: OutputTag[T])</p>
<p>针对这种场景，需要设计一套修复机制，将我们的迟到丢到另一个流中单独计算，然后通过合并的方式，合并到我们的主状态中。</p>

        </div>
        
<blockquote class="copyright">
    <p><strong>本文链接 : </strong><a class="permalink" href="https://123zhangzhenbin.gitee.io/zzbomb/2020/10/27/202010270852-flink-windows/">https://123zhangzhenbin.gitee.io/zzbomb/2020/10/27/202010270852-flink-windows/</a></p>
    <p><strong>This article is available under <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank" rel="noopener noreferrer">Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)</a> License</strong></p>
</blockquote>


    </article>
    
    <section id="comments">
        
    </section>


    

</main>


<aside style="" id="sidebar" class="aside aside-fixture">
    <div class="toc-sidebar">
        <nav id="toc" class="article-toc">
            <h3 class="toc-title">文章目录</h3>
            <ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#前言"><span class="toc-number">1.</span> <span class="toc-text">前言</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Flink-事件时间语义"><span class="toc-number">2.</span> <span class="toc-text">Flink 事件时间语义</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#Ingestion-Time"><span class="toc-number">2.1.</span> <span class="toc-text">Ingestion Time</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Event-Time"><span class="toc-number">2.2.</span> <span class="toc-text">Event Time</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Processing-Time"><span class="toc-number">2.3.</span> <span class="toc-text">Processing Time</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#使用场景"><span class="toc-number">2.4.</span> <span class="toc-text">使用场景</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Flink-窗口类型和水印"><span class="toc-number">3.</span> <span class="toc-text">Flink 窗口类型和水印</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#滚动窗口（Tumbling-Windows）"><span class="toc-number">3.1.</span> <span class="toc-text">滚动窗口（Tumbling Windows）</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#滑动窗口（Sliding-Windows）"><span class="toc-number">3.2.</span> <span class="toc-text">滑动窗口（Sliding Windows）</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#会话窗口（Session-Windows）"><span class="toc-number">3.3.</span> <span class="toc-text">会话窗口（Session Windows）</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#水印"><span class="toc-number">3.4.</span> <span class="toc-text">水印</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Flink-如何保证exactly-once语义"><span class="toc-number">4.</span> <span class="toc-text">Flink 如何保证exactly-once语义</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Flink-迟到数据如何处理"><span class="toc-number">5.</span> <span class="toc-text">Flink 迟到数据如何处理</span></a></li></ol>
        </nav>
    </div>
</aside>





        </section>
        <footer class="hidden lg:block fixed bottom-0 left-0 sm:w-1/12 lg:w-1/6 bg-gray-100 z-40">
    
    <div class="footer-social-links">
        
            <a href="https://gitee.com/123zhangzhenbin" target="_blank" rel="noopener">
                <i class="iconfont icon-github"></i>
            </a>
        
    </div>
    
    <p style="display: block;text-align: center;font-size: 13px;"><a href="https://beian.miit.gov.cn/" target="_blank">粤ICP备16013026号</a></p>
    
        <p class="footer-custom"><a href="https://beian.miit.gov.cn/" target="_blank">粤ICP备16013026号</a></p>
        <p class="theme-brand">Theme by <a href="https://github.com/fengkx/hexo-theme-purer" target="_blank" rel="nofollow noopener noreferrer noopener">hexo-theme-purer</a></p>

    
</footer>

        <div id="mask" class="hidden mask fixed inset-0 bg-gray-900 opacity-75 z-40"></div>
        <div id="search-view-container" class="hidden shadow-xl"></div>
        
<script src="/zzbomb/js/dom-event.min.js"></script>

<script src="//cdn.jsdelivr.net/npm/yox@1.0.0-alpha.121/dist/standard/prod/yox.min.js"></script>


<script src="/zzbomb/js/search.min.js"></script>



    <script src="//cdn.jsdelivr.net/npm/lightgallery.js@1.1.3/dist/js/lightgallery.min.js"></script>
    
<script src="/zzbomb/js/light-gallery.min.js"></script>





    </body>
</html>
